package com.boardour.ffmpegdemo.player;

import android.text.TextUtils;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.OnLifecycleEvent;

/**
 * 音视频解码播放，Java层
 */
public class FFPlayer implements LifecycleObserver, SurfaceHolder.Callback {


    static {
        System.loadLibrary("ffmpegdemo");
    }

    // 在native层的对象
    public final long nativePrt;
    // 音视频路径
    private String path;
    private OnPrepareListener onPrepareListener;
    private OnErrorListener onErrorListener;


    public FFPlayer() {
        nativePrt = n_videoPlayer();
    }

    public void setPath(String path) {
        this.path = path;
    }

    /**
     * 视频播放准备工作
     */
    public void prepare() {
        if (TextUtils.isEmpty(path)) {
            throw new RuntimeException("path is null please call method setPath");
        }
        n_prepare(nativePrt, path);
    }

    /**
     * 开始播放视频
     */
    public void start() {
        n_start(nativePrt);
    }

    /**
     * 停止播放视频
     */
    public void stop() {
        n_stop(nativePrt);
    }

    /**
     * 回收资源
     */
    public void release() {
        Log.e("TAG","release");
        n_release(nativePrt);
    }


    // native 层 =====================================================
    // native回调 ，准备完成
    private void onPrepared() {
        Log.e("TAG", "onPrepared from native");
        if (onPrepareListener != null) {
            onPrepareListener.onPrepared();
        }
    }

    // native回调 ，错误回调
    private void onError(int errorCode, String msg) {
        StringBuffer sb = new StringBuffer();
        switch (errorCode) {
            case ErrorCode.AV_FORMAT_OPEN_INPUT:
                sb.append("打开视频格式失败:");
                break;
            case ErrorCode.AV_FORMAT_FIND_STREAM_INFO:
                sb.append("查找音视频数据失败:");
                break;
            case ErrorCode.AV_CODEC_FIND_DECODER:
                sb.append("查找音视频解码器失败:");
                break;
            case ErrorCode.AV_CODEC_ALLOC_CONTEXT:
                sb.append("开辟解码器内存失败:");
                break;
            case ErrorCode.AV_CODEC_PARAMETERS_TO_CONTEXT:
                sb.append("拷贝音视频参数到解码器失败:");
                break;
            case ErrorCode.AV_CODEC_OPEN:
                sb.append("打开解码器失败:");
                break;
            case ErrorCode.AV_FORMAT_NULL:
                sb.append("没有打开音频或视频数据失败:");
                break;
        }
        sb.append(msg);
        if (onErrorListener != null) {
            onErrorListener.onError(errorCode, sb.toString());
        }
        Log.e("TAG", sb.toString());
    }

    private native long n_videoPlayer();

    private native void n_prepare(long nativePrt, String path);

    private native void n_start(long nativePrt);

    private native void n_stop(long nativePrt);

    private native void n_release(long nativePrt);

    private native void n_surface(long nativePrt, Surface surface);
    // native 层 =====================================================


    public void setOnPrepareListener(OnPrepareListener onPrepareListener) {
        this.onPrepareListener = onPrepareListener;
    }

    public void setOnErrorListener(OnErrorListener onErrorListener) {
        this.onErrorListener = onErrorListener;
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    public void onStop(LifecycleOwner owner) {
        stop();
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    public void onDestroy(LifecycleOwner owner) {
        release();
        owner.getLifecycle().removeObserver(this);
    }

    // Surface相关========================
    public void setSurfaceView(SurfaceView surfaceView) {
        SurfaceHolder holder = surfaceView.getHolder();
        holder.addCallback(this);
    }

    @Override
    public void surfaceCreated(@NonNull SurfaceHolder holder) {

    }

    @Override
    public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
        Surface surface = holder.getSurface();
        n_surface(nativePrt, surface);
    }

    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder holder) {

    }

    // Surface相关========================
}
